/**
 * 源代码地址：https://codesandbox.io/s/5nj1t?file=/src/index.js
 * @author felix.mueller
 */

import conditionalFlows from 'bpmnlint/rules/conditional-flows'
import endEventRequired from 'bpmnlint/rules/end-event-required'
import eventSubProcessTypedStartEvent from 'bpmnlint/rules/event-sub-process-typed-start-event'
import fakeJoin from 'bpmnlint/rules/fake-join'
import labelRequired from 'bpmnlint/rules/label-required'
import noBpmnDi from 'bpmnlint/rules/no-bpmndi'
import noComplexGateway from 'bpmnlint/rules/no-complex-gateway'
import noDisconnected from 'bpmnlint/rules/no-disconnected'
import noDuplicateSequenceFlows from 'bpmnlint/rules/no-duplicate-sequence-flows'
import noGatewayJoinFake from 'bpmnlint/rules/no-gateway-join-fork'
import noImplicitSplit from 'bpmnlint/rules/no-implicit-split'
import noInclusiveGateway from 'bpmnlint/rules/no-inclusive-gateway'
import singleBlankStartEvent from 'bpmnlint/rules/single-blank-start-event'
import singleEventDefinition from 'bpmnlint/rules/single-event-definition'
import startEventRequired from 'bpmnlint/rules/start-event-required'
import subProcessBlankStartEvent from 'bpmnlint/rules/sub-process-blank-start-event'
import superfluousGateway from 'bpmnlint/rules/superfluous-gateway'

type Reporter = {
  report(id: string, message: string, path?: string[] | Record<string, string[] | string>): void
}
export type LintRuleLinter = {
  check: (node: BpmnElement, reporter: Reporter) => undefined | void
}

const cache: { [key: string]: LintRuleLinter } = {}

export type LintRuleFlag = 'warn' | 'error' | 'info' | 'off'
export type LintRules = Record<string, LintRuleFlag>

/**
 * A resolver that caches rules and configuration as part of the bundle,
 * making them accessible in the browser.
 *
 * @param {Object} cache
 */
class Resolver {
  constructor() {}
  resolveRule(pkg: string, ruleName: string) {
    const rule = cache[pkg + '/' + ruleName]
    if (!rule) {
      throw new Error('cannot resolve rule <' + pkg + '/' + ruleName + '>')
    }
    return rule
  }
  resolveConfig(pkg: string, configName: string) {
    throw new Error('cannot resolve config <' + configName + '> in <' + pkg + '>')
  }
}

const resolver = new Resolver()

const rules: LintRules = {
  'conditional-flows': 'error',
  'end-event-required': 'error',
  'event-sub-process-typed-start-event': 'error',
  'fake-join': 'warn',
  'label-required': 'off',
  'no-bpmndi': 'error',
  'no-complex-gateway': 'error',
  'no-disconnected': 'error',
  'no-duplicate-sequence-flows': 'error',
  'no-gateway-join-fork': 'error',
  'no-implicit-split': 'error',
  'no-inclusive-gateway': 'error',
  'single-blank-start-event': 'error',
  'single-event-definition': 'error',
  'start-event-required': 'error',
  'sub-process-blank-start-event': 'error',
  'superfluous-gateway': 'warn',
}

const config = {
  rules: rules,
}

const bundle = {
  resolver: resolver,
  config: config,
}
cache['bpmnlint/conditional-flows'] = conditionalFlows
cache['bpmnlint/end-event-required'] = endEventRequired
cache['bpmnlint/event-sub-process-typed-start-event'] = eventSubProcessTypedStartEvent
cache['bpmnlint/fake-join'] = fakeJoin
cache['bpmnlint/label-required'] = labelRequired
cache['bpmnlint/no-bpmndi'] = noBpmnDi
cache['bpmnlint/no-complex-gateway'] = noComplexGateway
cache['bpmnlint/no-disconnected'] = noDisconnected
cache['bpmnlint/no-duplicate-sequence-flows'] = noDuplicateSequenceFlows
cache['bpmnlint/no-gateway-join-fork'] = noGatewayJoinFake
cache['bpmnlint/no-implicit-split'] = noImplicitSplit
cache['bpmnlint/no-inclusive-gateway'] = noInclusiveGateway
cache['bpmnlint/single-blank-start-event'] = singleBlankStartEvent
cache['bpmnlint/single-event-definition'] = singleEventDefinition
cache['bpmnlint/start-event-required'] = startEventRequired
cache['bpmnlint/sub-process-blank-start-event'] = subProcessBlankStartEvent
cache['bpmnlint/superfluous-gateway'] = superfluousGateway

export default bundle

export { config, resolver }
